//*************************************************************************************
/** \file task_temperature.cc
 *    This file contains a class which reads a temperature sensor. Readings from the
 *    sensor are averaged over a given period, and the average can be grabbed by a
 *    radio task to be transmitted to a base station somewhere. 
 *
 *  Revisions:
 *    \li 12-26-07 JRR Original file
 *    \li 12-30-07 JRR Corrected spelling of Fahrenheit
 *    \li 06-01-08 JRR Changed serial stuff to use base_text_serial and descendents
 */
//*************************************************************************************


#include <stdlib.h>
#include <avr/io.h>
#include "avr_1wire.h"						// For 1-wire sensors
#include "avr_ds1822.h"						// The DS1822 temperature sensor
#include "base_text_serial.h"				// For writing things to serial devices
#include "global_debug.h"					// Debugging from all parts of the program
#include "stl_timer.h"						// Timer measures real time
#include "task_temperature.h"				// Header for this task


//-------------------------------------------------------------------------------------
/** This constructor creates a new temperature reading task object. The user must have
 *  previously created an object of class avr_ds1822 which runs the temperature sensor.
 *  @param p_sensor A pointer to an object of type avr_ds1822
 *  @param a_timer A reference to the task timer
 *  @param interval_time A time stamp containing the time interval between runs
 */

task_temperature::task_temperature (avr_ds1822* p_sensor, task_timer& a_timer, 
									time_stamp interval_time)
	: stl_task (a_timer, interval_time)
{
	the_sensor = p_sensor;

	// Zero the averaging registers
	sum_of_readings = 0L;
	num_readings = 0;

// 	GLOB_DEBUG ("DS1822 task constructor\r\n");
}


//-------------------------------------------------------------------------------------
/** This is the function which runs when it is called by the task scheduler. It gets a
 *  temperature reading from the DS1822 sensor, then saves that reading and adds it to
 *  the averaging sum so that an average temperature can be computed later.
 *  @param state The state of the task when this run method begins running
 *  @return The state to which the task will transition, or STL_NO_TRANSITION if no
 *      transition is called for at this time
 */

char task_temperature::run (char state)
{
	#ifdef USE_FAHRENHEIT
		most_recent_reading = the_sensor->fahrenheit ();
	#else
		most_recent_reading = the_sensor->celsius ();
	#endif

	// Also save the reading to the averaging registers for averaging out later
	sum_of_readings += most_recent_reading;
	num_readings++;

	#ifdef USE_FAHRENHEIT
	GLOB_DEBUG ("Temp. " << (get_latest () / 10) << "." << get_latest () % 10 
		<< " F" << endl);
	#else
	GLOB_DEBUG ("Temp. " << (get_latest () / 10) << "." << get_latest () % 10 
		<< " C" << endl);
	#endif

	return (STL_NO_TRANSITION);
}


//-------------------------------------------------------------------------------------
/** This method computes and returns the average reading from the number of readings 
 *  and the sum of those readings' values. These sums have been saved up since the
 *  last time this method was called. When this method is called, it zeros the
 *  number of readings and the sum. If there hasn't been any time to measure the
 *  temperature since this function was last called, it returns 0. 
 *  @return The average temperature since the last reading was taken
 */

int task_temperature::get_average (void)
{
	int average = (int)(sum_of_readings / num_readings);
	sum_of_readings = 0L;
	num_readings = 0;

	return (average);
}


//-------------------------------------------------------------------------------------
/** This method returns the most recently measured temperature, in whatever units are
 *  specified by defining or not defining the macro USE_FAHRENHEIT. 
 *  @return The most recently read temperature
 */

int task_temperature::get_latest (void)
{
	return (most_recent_reading);
}
